package parser

import (
	"fmt"
	"log"
	"strconv"

	"gitee.com/chuanjinge/go-interpreter-waiig/src/monkey/ast"
	"gitee.com/chuanjinge/go-interpreter-waiig/src/monkey/lexer"
	"gitee.com/chuanjinge/go-interpreter-waiig/src/monkey/tok"
)

// 定义运算符优先级
const (
	_           int = iota // 占位0
	LOWEST                 // 它代表着最低的优先级，很可能用于兜底，在语法解析规则里作为最基础的比较层级。
	EQUAL                  // 相等比较操作符通常有相对较高一点的优先级，比基础的最低优先级要高。
	LESSGREATER            // 对应 > 或 < 比较操作符，在运算优先级上高于相等操作符，因为比较大小先于判断是否相等
	SUM                    // 加法 + 操作符，加法在四则运算里优先级高于比较运算，所以它的优先级更高。
	PRODUCT                // 对应 乘法* 和 除法/ 操作符，乘法优先级高于加法，所以它的优先级在这组常量里也是较高的。
	PREFIX                 // 用于像 -X （负号操作） 或者 !X （逻辑非操作）这类前缀操作符，前缀操作往往先于常规的四则运算和比较运算执行，优先级较高。
	CALL                   // 关联函数调用，比如 myFunction(X)，函数调用在语法解析时通常优先级较高，因为要先解析函数名和参数，再处理函数返回值参与的其他运算。
)

// 定义具体运算符对应的优先级
var precedences = map[tok.TokenType]int{
	tok.EQUAL:    EQUAL,
	tok.NOT_EQ:   EQUAL,
	tok.LT:       LESSGREATER,
	tok.GT:       LESSGREATER,
	tok.PLUS:     SUM,
	tok.SUB:      SUM,
	tok.SLASH:    PRODUCT,
	tok.MULTI:    PRODUCT,
	tok.LPAREN:   CALL, // 左括号如果遍历到的话，意味着是一次函数调用；注意此处的优先级是在中缀运算符中使用，非中缀运算符的时候我们遍历到会执行响应的func.
	tok.LBRACKET: CALL, // 中括号其实也相当于一次函数调用
}

type Parser struct {
	l         *lexer.Lexer
	curToken  tok.Token // 与 peekToken 配合
	nextToken tok.Token // 始终指向下一个要处理的词法单元
	errors    []string  // 收集对于语句解析的所有错误（一般来说当对一个语句解析出错之后，后边所有未解析的词法单元会被忽略，直到遇到下一个表征为语句的词法单元出现，我们做下一次的解析，所以有几个错误就意味着有几条语句出错了，不会出现一条语句多个错误的情况）

	// 解析器用到的普拉特解析函数
	prefixParseFns map[tok.TokenType]prefixParseFunction
	infixParseFns  map[tok.TokenType]infixParseFunction
}

// 构造方法，此处是依赖注入(此种方法便于扩展)
func New(l *lexer.Lexer) *Parser {
	p := &Parser{l: l}
	// 初始化Parser的上下文，读取两个词法单元
	p.rollupToken() // 第一次rollup,填充nextToken
	p.rollupToken() // 第二次rollup,curToken被nextToken填充，nextToken被更新填充

	// let语句 return语句都有自己的处理方法
	// 其余的均走表达式处理方法
	// 表达式处理方法中对于词法单元才去 前缀函数 + 中缀函数 的处理方式，每个词法单元拥有不同的前缀、中缀函数，可能同时应用这两个函数，也可能仅应用其中一个。
	// 前缀处理函数
	p.prefixParseFns = make(map[tok.TokenType]prefixParseFunction)
	p.infixParseFns = make(map[tok.TokenType]infixParseFunction)

	// - 注册表达式中不同词法单元的前缀、中缀处理函数
	p.registerPrefix(tok.IDENT, p.parseIdentifier)            // 解析标识符的话用 parseIdentifier
	p.registerPrefix(tok.INT, p.parseIntegerLiteral)          // 解析数字的话
	p.registerPrefix(tok.TRUE, p.parseBooleanLiteral)         // 解析布尔值
	p.registerPrefix(tok.FALSE, p.parseBooleanLiteral)        // ~~
	p.registerPrefix(tok.BANG, p.parsePrefixExpression)       // ! 按照前缀表达式处理
	p.registerPrefix(tok.SUB, p.parsePrefixExpression)        // - 按照前缀表达式处理
	p.registerPrefix(tok.LPAREN, p.parseGroupedExpression)    // ( 解析左括号
	p.registerPrefix(tok.IF, p.parseIfExpression)             // ( 解析if语句(此处当作表达式)
	p.registerPrefix(tok.FUNCTION, p.parseFunctionExpression) // 解析fn表达式
	p.registerPrefix(tok.STR, p.parseStringExpression)        //
	p.registerPrefix(tok.LBRACKET, p.parseArrayExpression)    // 解析数组表达式
	p.registerPrefix(tok.LBRACE, p.parseMapExpression)        // 解析哈希字典表达式

	// 中缀处理函数
	p.registerInfix(tok.EQUAL, p.parseInfixExpression)
	p.registerInfix(tok.NOT_EQ, p.parseInfixExpression)
	p.registerInfix(tok.LT, p.parseInfixExpression)
	p.registerInfix(tok.GT, p.parseInfixExpression)
	p.registerInfix(tok.PLUS, p.parseInfixExpression)
	p.registerInfix(tok.SUB, p.parseInfixExpression)
	p.registerInfix(tok.SLASH, p.parseInfixExpression)
	p.registerInfix(tok.MULTI, p.parseInfixExpression)
	// 函数调用可以看做是一种中缀运算 add(x, y) 其中add是左表达式，(是中缀， x,y构成的参数列表是
	p.registerInfix(tok.LPAREN, p.parseCallExpression)
	// 数组下标访问可以看作是一种中缀运算 arr[0] 其中 arr是左表达式, [是中缀，0是参数
	p.registerInfix(tok.LBRACKET, p.parseIndexExpression)

	return p
}

func (p *Parser) registerPrefix(tokenType tok.TokenType, fn prefixParseFunction) {
	p.prefixParseFns[tokenType] = fn
}
func (p *Parser) registerInfix(tokenType tok.TokenType, fn infixParseFunction) {
	p.infixParseFns[tokenType] = fn
}

// 将peekToken移动到curToken,然后读取下一个token到peekToken
func (p *Parser) rollupToken() {
	p.curToken = p.nextToken
	log.Println("***scanToken:  ", p.curToken.Literal, p.curToken.Type)
	p.nextToken = p.l.NextToken()
}

// 获取当前token的优先级
func (p *Parser) curPrecedence() int {
	index, ok := precedences[p.curToken.Type]
	if !ok {
		p.errors = append(p.errors, fmt.Sprintf("无法获取当前令牌的优先级:type:%s", p.curToken.Type))
		return LOWEST
	}
	return index
}

// 获取下一个token的优先级
func (p *Parser) nextPrecedence() int {
	index, ok := precedences[p.nextToken.Type]
	if !ok {
		log.Printf("================%#v", p.nextToken)
		// 右括号在此处就会除法这个，而且我们把右括号的优先级返回为默认最低级，这样就可以避免其在中缀表达式中具有粘合性而被捕捉到
		//p.errors = append(p.errors, fmt.Sprintf("无法获取下一个令牌的优先级:type:%s", p.nextToken.Type))
		return LOWEST
	}
	return index
}

// 将词法单元按照语法树的结构排列
func (p *Parser) ParseProgram() *ast.Program {
	// 初始化根节点
	program := &ast.Program{}
	program.Statements = []ast.Statement{} // 之前总是 make([]ast.Statement, 0)，原来这样也行

	// 基于词法单元处理 语句，合法语句加入到根节点的语句集合之中
	for p.curToken.Type != tok.EOF && p.curToken.Type != tok.ILLEGAL {
		log.Printf("ParseProgram: %s\n", p.curToken.Literal)
		// log.Println("curtoken type:", p.curToken.Type)
		stmt := p.parseStatement()
		if stmt != nil {
			program.Statements = append(program.Statements, stmt)
		}
		p.rollupToken()
	}

	if p.curToken.Type == tok.ILLEGAL {
		fmt.Printf("illegal char terminate parsing:%#v\n", p.curToken.Literal)
	}

	return program
}

// 返回结果必须是 Statement 接口的实现，即一个 AST 语句。
// 非语句相关的token进入该方法会被抛弃掉，然后继续对下一个token进行检查
// 理论上进入该方法的token都是语句相关的，比如 let语句的相关词法单元是let，我们在 parse过程中会把后续所有单元都吞并处理，直到遇到下一个语句相关的词法单元，比如另一个let，或者return
func (p *Parser) parseStatement() ast.Statement {
	log.Println("parseStatement: ", p.curToken.Literal)
	switch p.curToken.Type {
	case tok.LET:
		return p.parseLetStmt()
	case tok.RETURN:
		return p.parseReturnStmt()
	default:
		// 除去let和return语句其余的均按照表达式语句处理
		return p.parseExpressionStmt()
	}
}

// 调用该方法的前提是调用方必须判断出来了当前token的类型是 LET 类型
func (p *Parser) parseLetStmt() *ast.LetStatement {
	// 将首个词法单元计入LetStatement的元数据
	stmt := &ast.LetStatement{Token: p.curToken}

	// 继续判断下一个词法单元，对于LET语句来说，下一个必然是一个 标识符
	// 注意该方法会执行rollup操作，所以后续可以直接使用 curToken
	if !p.expectNext(tok.IDENT) {
		return nil
	}

	stmt.Name = &ast.Identifier{
		Token: p.curToken,
		Value: p.curToken.Literal,
	}

	// 再继续下一个应该是等号;验证通过会自动移动到下一个token
	if !p.expectNext(tok.ASSIGN) {
		log.Printf("parseLetStmt should be =, got %s", p.nextToken.Literal)
		return nil
	}
	// 开始解析表达式
	p.rollupToken()
	stmt.Value = p.parseExpression(LOWEST)

	// 理论上此时指向的是最后的分号的前一个token
	if !p.expectNext(tok.SEMICOLON) {
		log.Printf("parseLetStmt value: %#v\n", stmt.Value)
		log.Printf("parseLetStmt should be ;, got %s\n", p.nextToken.Literal)
		return nil
	}

	return stmt
}

// 解析return语句
func (p *Parser) parseReturnStmt() *ast.ReturnStatement {
	stmt := &ast.ReturnStatement{Token: p.curToken}
	p.rollupToken() // 跳到return后边去

	// 下一个token应该是一个表达式
	stmt.Value = p.parseExpression(LOWEST)

	// 理论上此时指向的是最后的分号的前一个token
	if !p.expectNext(tok.SEMICOLON) {
		log.Printf("parseReturnStmt should be ;, got %s", p.nextToken.Literal)
		return nil
	}
	return stmt
}

// 解析表达式 - 我们把表达式视为一种语句，因为他确实可以以单独的语句出现，虽然不会有什么正面或负面的影响!!
func (p *Parser) parseExpressionStmt() *ast.ExpressionStatement {
	stmt := &ast.ExpressionStatement{Token: p.curToken}
	stmt.Expression = p.parseExpression(LOWEST) // 初次调用表达式解析函数，都从优先级0开始

	if p.nextTokenTypeIs(tok.SEMICOLON) {
		p.rollupToken() // 如果解析完表达式之后下一个是分号，那么将指针移动到分号处!!
	}

	return stmt
}

// 解析表达式。
// 碰到一个词法单元，就尝试应用前缀函数，如果该词法单元的后继节点不是结束符并且优先级要更高，则按照中缀运算符处理
// 表达式的种类很多，比如
// -5;
// a;
// a+b;
// 1+2;
// add(1+2);
// @param int precedence 优先级，表示的是当前curToken的优先级，用来与后续的运算符进行优先级比较，决定是否要进行粘合
func (p *Parser) parseExpression(precedence int) ast.Expression {
	// 看看当前token是否拥有前缀处理函数，有的话执行，没有的话直接返回
	prefixFunc := p.prefixParseFns[p.curToken.Type]
	if prefixFunc == nil {
		return nil
	}
	leftExp := prefixFunc()
	log.Printf("parseExpression:left: %#v; prec: %d; nextToken:%s; nextPrec: %d\n", leftExp, precedence, p.nextToken.Literal, p.nextPrecedence())

	// 如果当前词法单元之后不是结束符的话，看一下是否要进行粘合
	// + 自己的优先级比较低，被右侧运算符黏住了
	// + 自己的优先级不低的话，就不管右边了，直接返回；此时自己的上级函数肯定会进行继续的move操作
	// 总而言之，当前方法是尽量的去结合那些比自己优先级高的节点，直到无法结合再返回
	// 由于初始调用该方法传入的优先级是0，且会发生递归调用，这就意味着最外层调用会尝试结合所有的节点
	// - 以 a+b*c-d 为例：
	// -- a进入该函数时携带的prec(0), a被prefix函数处理为节点a, a的优先级0小于+号的优先级, 所以此处构成一个可能的中缀表达式，
	// -- 注意我们可以简单理解 当前优先级小于其后优先级的话，即为中缀表达式的充要条件，作为中缀表达式来处理即可。
	// -- b*c-d 进入中缀表达式右侧表达式的处理逻辑，右侧表达式仍然进入当前 parseExpression 函数，且携带的优先级是 + 加号的优先级，
	// -- 根据当前逻辑+是小于*的，所以仍然要进行向右的结合，b最终和c结合形式 {*,b,c} 的结构，最终因为 * 的优先级大于-，而无法继续向右结合，
	// -- 这时候 curToken 指向了 c, 函数栈递归回到了最初 precedence 为0的栈里，prec(0) 已经最大程度结合了右边的节点，
	// -- 此时回到此处的时候构成了一个新的左侧节点，他的初始优先级仍然是左侧节点中的最低优先级，也就是0，
	// -- 现在他以新的身份继续尝试向右侧去结合所有可以结合的节点，历史在循环中前进，直到结束符。
	for p.nextToken.Type != tok.SEMICOLON && p.nextToken.Type != tok.EOF && precedence < p.nextPrecedence() {
		infixFunc := p.infixParseFns[p.nextToken.Type]
		if infixFunc == nil {
			// 没有该中缀运算符的可操作函数，放弃处理
			return leftExp
		}
		// 指向到中缀运算符
		p.rollupToken()
		// 带着左表达式给中缀运算符找右表达式
		leftExp = infixFunc(leftExp)
	}

	return leftExp
}

// !+[parseConcreteExpress]解析具体的表达式

// 解析前缀表达式（也可以看做是语句）
func (p *Parser) parsePrefixExpression() ast.Expression {
	expr := &ast.PrefixExpression{
		Token:    p.curToken,
		Operator: p.curToken.Literal, // 比如 !
	}

	// 继续读取下一个token
	p.rollupToken()
	// 注意此处的优先级要设置为 PREFIX，基本上是最高优先级了，此时进入parseExpression后基本都是原样返回，除非有函数调用
	expr.Right = p.parseExpression(PREFIX) // 此处是递归操作，直到把所有的token都应用了前缀函数
	return expr
}

// 左括号表达式，碰到之后，直接从括号之后开始解析表达式
func (p *Parser) parseGroupedExpression() ast.Expression {
	p.rollupToken()
	exp := p.parseExpression(LOWEST)
	// 理论上表达式之后是右括号
	if p.nextToken.Type != tok.RPAREN {
		return nil
	}
	p.rollupToken() // 移动到右括号上
	// 此时指向右括号
	return exp
}

// 左中括号，碰到之后就开始解析数组表达式
func (p *Parser) parseArrayExpression() ast.Expression {
	array := &ast.Array{
		Token: p.curToken,
	}
	p.rollupToken()
	// 将中间的token搞到一堆中
	elements := []ast.Expression{}
	for p.curToken.Type != tok.RBRACKET {
		elements = append(elements, p.parseExpression(LOWEST))
		p.rollupToken() // 移动到下一个token上
		for p.curToken.Type == tok.COMMA {
			p.rollupToken() // 跳过所有的逗号token
		}
	}
	// 最后的curtoken应该是在右中括号上
	if p.curToken.Type != tok.RBRACKET {
		p.errors = append(p.errors, fmt.Sprintf("array expression has wrong struct, should got ], now is %s", p.curToken.Literal))
		return nil
	}
	array.Elements = elements
	return array
}

// 左大括号，碰到之后就开始解析字典表达式
func (p *Parser) parseMapExpression() ast.Expression {
	m := &ast.HashLiteral{
		Token: p.curToken,
	}
	m.Pairs = map[ast.Expression]ast.Expression{}

	// 此时应该是 exp:exp 后边是逗号或者右括号
	for !p.nextTokenTypeIs(tok.RBRACE) && !p.nextTokenTypeIs(tok.EOF) {
		// 移动到下一个token上
		// 一进入循环就rollup有一个最大的好处就是可以统一初始化进入和循环进入这两种操作，免得还得再初始化进入和循环进入的时候分别调用rollup
		p.rollupToken()
		key := p.parseExpression(LOWEST)
		if !p.expectNext(tok.COLON) {
			return nil
		}
		p.rollupToken() // 移动到tok.COLON之后的下一个token
		value := p.parseExpression(LOWEST)
		m.Pairs[key] = value

		// 如果是右大括号，说明结束了
		if p.nextTokenTypeIs(tok.RBRACE) {
			break
		}

		// 未结束的情况下，下一个token应该是逗号才对，我们要跳过去该逗号
		if !p.expectNext(tok.COMMA) { // 该操作在true的时候会跳到目标token之上，false的时候不动
			return nil
		}
	}

	if !p.expectNext(tok.RBRACE) {
		return nil
	}

	// 如果没有经过任何for循环的洗礼，此处返回的就是空的ast.HashLiteral
	return m
}

// if语句表达式
func (p *Parser) parseIfExpression() ast.Expression {
	ifExp := &ast.IfExpression{
		Token: tok.Token{Type: tok.IF, Literal: "if"},
	}
	log.Println("ParseIfExpression...")
	// 只要碰到了 【if】token， 就继续前进，理论上会碰到 【(】token，继续前进后应该是一个表达式
	if p.nextToken.Type != tok.LPAREN {
		p.errors = append(p.errors, fmt.Sprintf("if expression has wrong struct, should got (, now is %s", p.nextToken.Literal))
		return nil
	}
	p.rollupToken()
	// 解析表达式，该表达式应该是在括号之内，应用 parseGroupedExpression 该方法会保证括号的存在
	exp := p.parseExpression(LOWEST)
	if exp == nil {
		p.errors = append(p.errors, "if expression has wrong struct, got nil body") // 空body也是有可能的
	}
	// 条件表达式解析完毕
	ifExp.Condition = exp
	// 此时指向的token应该是 【)】,我们应该在parseBlockStmts中判断下一个是不是 {}
	ifExp.Consequence = p.parseBlockStmts()
	// 如果有else的话，还得解析else
	if p.nextToken.Type == tok.ELSE {
		p.rollupToken()
		ifExp.Alternative = p.parseBlockStmts()
	}
	return ifExp
}

// 左大括号就是blockStatement
// 此时nextToken在LBRACE的前一个token
func (p *Parser) parseBlockStmts() *ast.BlockStatement {
	blkStmt := &ast.BlockStatement{
		Token: p.curToken,
	}
	// 只要碰到了 【{】，把后续的内容组成多条表达式
	if p.nextToken.Type != tok.LBRACE {
		log.Printf("block statements has wrong struct, should got {, now is %s\n", p.nextToken.Literal)
		p.errors = append(p.errors, fmt.Sprintf("block statements has wrong struct, should got {, now is %s", p.nextToken.Literal))
		return nil
	}
	p.rollupToken() // 移动到【(】
	p.rollupToken() // 移动到下一个令牌
	if p.curToken.Type == tok.RBRACE {
		blkStmt.Statements = []ast.Statement{}
		return blkStmt // 如果这个令牌是 【)】说明语句体为空
	}
	stmts := []ast.Statement{}
	// 只要不是 【}】 就一直尝试解析
	// 不断调用parseStatement，直到遇见右大括号}或token.EOF
	for p.curToken.Type != tok.RBRACE && p.curToken.Type != tok.EOF {
		// 语句解析最后都指向了分号，或者}之前的最后一个token(后者是因为优先级太低无法继续粘合停止的)
		stmt := p.parseStatement()
		if stmt != nil {
			stmts = append(stmts, stmt)
		}
		// 不管当前指针指向的是分号还是}之前的最后一个token，我们都要移动一下子进行判断
		p.rollupToken()
	}
	// 最后应该是 【}】
	if p.curToken.Type != tok.RBRACE {
		p.errors = append(p.errors, fmt.Sprintf("block statements has wrong struct, should got }, now is %s", p.curToken.Literal))
		return nil
	}
	blkStmt.Statements = stmts
	return blkStmt
}

func (p *Parser) parseFunctionExpression() ast.Expression {
	fnExp := &ast.FunctionalLiteral{
		Token: p.curToken,
	}
	if p.nextToken.Type != tok.LPAREN {
		p.errors = append(p.errors, fmt.Sprintf("fn expression has wrong struct, should got (, now is %s", p.nextToken.Literal))
		return nil
	}
	p.rollupToken()
	fnExp.Parameters = p.parseFunctionParameter()

	// 开始解析块语句
	fnExp.Body = p.parseBlockStmts()
	return fnExp
}

// 解析函数的参数列表
func (p *Parser) parseFunctionParameter() []*ast.Identifier {
	if p.nextToken.Type == tok.RPAREN {
		p.rollupToken()
		return nil // 空参数列表
	}
	// 开始解析参数列表
	params := []*ast.Identifier{}
	for p.nextToken.Type != tok.RPAREN && p.nextToken.Type != tok.EOF {
		p.rollupToken()
		params = append(params, &ast.Identifier{Token: p.curToken, Value: p.curToken.Literal})
		if p.nextToken.Type == tok.COMMA {
			p.rollupToken() // 跳过逗号
		}
	}

	// 如果下一个不是 【)】 则报错
	if p.nextToken.Type != tok.RPAREN {
		p.errors = append(p.errors, fmt.Sprintf("fn expression has wrong struct, should got ), now is %s", p.nextToken.Literal))
		return nil
	}
	p.rollupToken() // 跳到 )

	return params
}

// 解析字符串字面量表达式
func (p *Parser) parseStringExpression() ast.Expression {
	strExp := &ast.StringLiteral{
		Token: p.curToken,
		Value: p.curToken.Literal,
	}
	return strExp
}

// 解析中缀表达式
// @param ast.Expression left 表示的是中缀运算符左侧的表达式
// -- 当前token指针指向的就是中缀运算符
func (p *Parser) parseInfixExpression(left ast.Expression) ast.Expression {
	log.Printf("parseInfixExpression:left %+v\n", left)
	exp := &ast.InfixExpression{
		Token:    p.curToken,
		Operator: p.curToken.Literal,
		Left:     left,
	}

	// 中缀运算符的 右侧表达式 还得依赖 expression 解析器来表达
	// 传递的运算符优先级是当前中缀运算符的，但是解析的起始位置是中缀运算符的下一个节点
	curPrecedence := p.curPrecedence()
	p.rollupToken()
	exp.Right = p.parseExpression(curPrecedence)

	log.Printf("parseInfixExpression:result %+v\n", exp)
	return exp
}

// 解析 add(2,3) 这种函数调用
func (p *Parser) parseCallExpression(left ast.Expression) ast.Expression {
	callExp := &ast.CallExpression{
		Token:    p.curToken,
		Function: left,
	}

	// 开始填充参数列表
	callExp.Arguments = p.parseCallParameter()
	return callExp
}

// 有可能是字面量、标识符、中缀表达式等所有表达式类型
func (p *Parser) parseCallParameter() []ast.Expression {
	// 有可能是空参数列表
	if p.nextToken.Type == tok.RPAREN {
		p.rollupToken()
		return nil
	}
	p.rollupToken() // 开始按照逗号分割
	exps := []ast.Expression{}
	for p.curToken.Type != tok.RPAREN && p.curToken.Type != tok.EOF {
		exp := p.parseExpression(LOWEST)
		if exp != nil {
			exps = append(exps, exp)
		}
		p.rollupToken()
	}

	// 理论上此时应该指向的是 【)】
	if p.curToken.Type != tok.RPAREN {
		p.errors = append(p.errors, "parseCallParameter should be ), got %s", p.curToken.Literal)
	}

	return exps
}

func (p *Parser) parseIndexExpression(left ast.Expression) ast.Expression {
	indexExp := &ast.IndexExpression{
		Token: p.curToken,
		Name:  left,
	}
	// 如果是空索引，报错
	if p.nextToken.Type == tok.RBRACKET {
		p.rollupToken()
		p.errors = append(p.errors, "parseIndexExpression get empty index")
		return nil
	}
	p.rollupToken()
	indexExp.Index = p.parseExpression(LOWEST)
	if p.nextToken.Type != tok.RBRACKET {
		p.errors = append(p.errors, fmt.Sprintf("parseIndexExpression has wrong struct, should got ], now is %s", p.nextToken.Literal))
		return nil
	}
	p.rollupToken()
	return indexExp
}

// 解析标识符(语句)
// 比如 标识符 foo 返回的就是一个 *Identity 类型的变量
func (p *Parser) parseIdentifier() ast.Expression {
	return &ast.Identifier{Token: p.curToken, Value: p.curToken.Literal}
}

// 解析整数字面量表达式（也可以看做是语句）
func (p *Parser) parseIntegerLiteral() ast.Expression {
	value, err := strconv.ParseInt(p.curToken.Literal, 0, 64) // 转换为int64的整数
	if err != nil {
		msg := fmt.Sprintf("error:parseIntegerLiteral can't parse %q as int64", p.curToken.Literal)
		p.errors = append(p.errors, msg)
		return nil
	}
	return &ast.IntegerLiteral{Token: p.curToken, Value: value}
}

// 解析布尔值
func (p *Parser) parseBooleanLiteral() ast.Expression {
	return &ast.BoolLiteral{Token: p.curToken, Value: p.curTokenTypeIs(tok.TRUE)}
}

// !-[parseConcreteExpress]

func (p *Parser) curTokenTypeIs(t tok.TokenType) bool {
	return p.curToken.Type == t
}
func (p *Parser) nextTokenTypeIs(t tok.TokenType) bool {
	return p.nextToken.Type == t
}

func (p *Parser) expectNext(expectTokenType tok.TokenType) bool {
	if p.nextTokenTypeIs(expectTokenType) {
		// 移动一下词法单元
		p.rollupToken()
		return true
	} else {
		log.Printf("!!!this string is %s\n", p.curToken.Literal)
		p.appendExpectTypeError(expectTokenType)
		return false
	}
}

// 输出所有的错误信息
func (p *Parser) Errors() []string {
	return p.errors
}

func (p *Parser) appendExpectTypeError(expectTokenType tok.TokenType) {
	msg := fmt.Sprintf("error:token type not match;expect=%s;got=%s\n", expectTokenType, p.nextToken.Type)
	p.errors = append(p.errors, msg)
}

// 构造 普拉特语法分析器
// 将解析函数与词法单元类型相关联。
// 每个词法单元最多关联两个解析函数，这取决于词法单元的位置，是位于前缀位置还是中缀位置。
// -- 每当遇到某个词法单元的时候，调用相关联的解析函数来解析对应的表达式，最后返回生成的AST节点。
type prefixParseFunction func() ast.Expression              // 前缀解析函数返回一个表达式节点，因为前缀运算符的左侧为空。
type infixParseFunction func(ast.Expression) ast.Expression // 中缀解析函数参数为左侧的内容，返回值TODO
